using System;
using Castle.Core;
using Castle.MicroKernel;
using Castle.MicroKernel.Registration;
using DeftTech.DuckTyping;

namespace WindsorDuckTyping {
    public static class DuckComponentExtensions {
        public static IKernel Kernel { get; set; }

        public interface IComponentReg {
            Type Implementation { get; }
            Type ServiceType { get; }
            string Name { get; }
        }

        private static void Duck<TDuck>(IComponentReg reg, InterceptorReference[] interceptors) {
            var targetType = reg.Implementation ?? reg.ServiceType;
            if (!DuckTyping.CanCast<TDuck>(targetType))
                throw new ApplicationException(string.Format("Can't duck type '{0}' to type '{1}'", targetType, typeof (TDuck)));
            Kernel.Register(Component.For<TDuck>()
                                .Interceptors(interceptors).Anywhere
                                .UsingFactoryMethod(k => DuckTyping.Cast<TDuck>(k.Resolve(reg.Name, reg.ServiceType))));
        }

        public static ComponentRegistration<object> Duck<TDuck>(this ComponentRegistration<object> reg, params InterceptorReference[] interceptors) {
            Duck<TDuck>(DuckTyping.Cast<IComponentReg>(reg), interceptors);
            return reg;
        }

        public static ComponentRegistration<TService> Duck<TDuck, TService>(this ComponentRegistration<TService> reg, params InterceptorReference[] interceptors) {
            Duck<TDuck>(DuckTyping.Cast<IComponentReg>(reg), interceptors);
            return reg;
        }
    }
}